package cn.dynamic.view.service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.*;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author liujieyu
 * @date 2022/11/9 19:12
 * @desciption
 */
@Component
public class LoggingReadComponent {

    private static final Logger logger = LoggerFactory.getLogger(LoggingReadComponent.class);

    // 时间格式装换器
    private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 获取到线程池数据
     * @param path
     * @param startTime
     * @return
     */
    public Map<String, Object> readLogging(String path, Date startTime, Date endTime, int number) {
        Map<String, Object> result = new HashMap<>(4);
        List<Map<String, Object>> data = new ArrayList<>(16);
        List<String> dateList = new ArrayList<>(16);
        try {
            Pattern p = Pattern.compile("(\\d{4})-(\\d{1,2})-(\\d{1,2}) (\\d{1,2}):(\\d{1,2}):(\\d{1,2})");
            FileReader f = new FileReader(path);
            BufferedReader b = new BufferedReader(f);
            int len = 0;
            int poolNumber = getPoolNumber(path);
            String s;
            String time = null;
            //判断是否到一行字符串
            while ((s = b.readLine()) != null) {
                Matcher m = p.matcher(s);
                while (m.find()) {
                    time = m.group(0);
                    break;
                }
                if (startTime != null && endTime != null) {
                    long l = LocalDateTime.parse(time, formatter).toInstant(OffsetDateTime.now().getOffset()).toEpochMilli();
                    if (l >= startTime.getTime() && l <= endTime.getTime()) {
                        len ++;
                        data.add(getPoolInfoByContent(s));
                        if (len % poolNumber == 0) {
                            dateList.add(time);
                        }
                        if (number != 0 && len >= poolNumber * number) {
                            break;
                        }
                    }
                } else if (startTime != null && endTime == null) {
                    long l = LocalDateTime.parse(time, formatter).toInstant(OffsetDateTime.now().getOffset()).toEpochMilli();
                    if (l >= startTime.getTime()) {
                        len ++;
                        data.add(getPoolInfoByContent(s));
                        if (len % poolNumber == 0) {
                            dateList.add(time);
                        }
                        if (number != 0 && len >= poolNumber * number) {
                            break;
                        }
                    }
                } else if (startTime == null && endTime != null) {
                    long l = LocalDateTime.parse(time, formatter).toInstant(OffsetDateTime.now().getOffset()).toEpochMilli();
                    if (l <= endTime.getTime()) {
                        len ++;
                        data.add(getPoolInfoByContent(s));
                        if (len % poolNumber == 0) {
                            dateList.add(time);
                        }
                        if (number != 0 && len >= poolNumber * number) {
                            break;
                        }
                    }
                } else {
                    len ++;
                    data.add(getPoolInfoByContent(s));
                    if (len % poolNumber == 0) {
                        dateList.add(time);
                    }
                    if (number != 0 && len >= poolNumber * number) {
                        break;
                    }
                }
            }
            result.put("data", data);
            result.put("timeList", dateList);
            b.close();
            f.close();
        } catch (IOException e) {
            logger.error("读取文件异常", e);
            throw new RuntimeException("读取文件异常");
        }

        return result;
    }

    /**
     * 解析文件获取线程池数量
     * @param path
     * @return
     */
    private int getPoolNumber(String path) {
        try {
            FileReader f = new FileReader(path);
            BufferedReader b = new BufferedReader(f);
            String s;
            String poolName = null;
            int number = 0;
            while ((s = b.readLine()) != null) {
                number ++;
                JSONObject jsonObject = JSON.parseObject(s);
                JSONObject thread_pool_metrics = jsonObject.getJSONObject("thread_pool_metrics");
                String tmpName = thread_pool_metrics.getString("poolName");
                if (poolName == null) {
                    poolName = tmpName;
                } else if (poolName.equals(tmpName)) {
                    number --;
                    break;
                }
            }
            b.close();
            f.close();
            return number;
        } catch (IOException e) {
            logger.error("读取文件异常", e);
            throw new RuntimeException("读取文件异常");
        }
    }

    /**
     * 根据日志内容格式化获取线程池数据
     * @param s
     * @return
     */
    private JSONObject getPoolInfoByContent(String s) {
        JSONObject jsonObject = JSON.parseObject(s);
        return jsonObject.getJSONObject("thread_pool_metrics");
    }

    /**
     * 生成一个临时路径
     * @param data
     * @return
     */
    public String createTmpFile(byte[] data) throws IOException {
        // 生成文件
        String path = System.getProperty("user.dir") + File.separator + UUID.randomUUID().toString();
        File file = new File(path);
        file.createNewFile();
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write(data);
        fileOutputStream.close();
        return path;
    }
}
